package cn.sc;

import cn.sc.collection.BaseCacheTemplate;
import cn.sc.collection.base.CacheObject;
import cn.sc.exceptions.CacheException;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName AbstractSimpleCache
 * @Author 谢卓才
 * @Description SimpleCache通用类，用来处理CacheObject的封装
 * @Date 2022/11/13 9:17
 */
public abstract class AbstractSimpleCache<V> implements BaseCacheTemplate<V>, SimpleCache<V> {

    @Override
    public V getCache(String key) {
        CacheObject<V> node = value(key);
        if (node.isExpired()) {
            delete(key);
            return null;
        }
        return node.getObject();
    }

    public List<V> getCacheAll(){
        List<CacheObject<V>> cacheObjects = valueAll();
        List<V> result = new ArrayList<>(cacheObjects.size());
        for (CacheObject<V> cacheObject : cacheObjects) {
            if(!cacheObject.isExpired()){
                result.add(cacheObject.getObject());
            }
        }
        return result;
    }

    @Override
    public List<V> getCacheList(String key) {
        List<V> result = new ArrayList<>();
        if (key.equals("*")){
            return getCacheAll();
        } else if(key.indexOf("*") == -1){
            V value = getCache(key);
            if (value!=null){
                result.add(value);
            }
        } else {
            for (String k : new KeyConversion().keyValue(key)) {
                V value = getCache(k);
                if (value!=null){
                    result.add(value);
                }
            }
        }
        return result;
    }

    @Override
    public V addCache(String key, V value) {
        return addCache(key,value,0);
    }

    @Override
    public V addCache(String key,V value,long time){
        return addCache(key,value,time,TimeUnit.SECONDS);
    }

    @Override
    public V addCache(String key, V value, long time, TimeUnit unit){
        if(key.indexOf("*") != -1){
            throw new CacheException("key非法");
        }
        return increase(key, createNode(value, unit.toMillis(time))).getObject();
    }

    @Override
    public Long deleteCache(String key) {
        if (!StringUtils.hasLength(key)){
            return 0L;
        }
        if (key.equals("*")){
            return cacheClear();
        } else if(key.indexOf("*") == -1){
            return delete(key);
        } else {
            Set<String> list = new KeyConversion().keyValue(key);
            return delete(list);
        }
    }

    @Override
    public V updateCache(String key, V value) {
        return addCache(key,value);
    }

    @Override
    public Long cacheSize(){
        return size();
    }


    private class KeyConversion{

        /**
         * 记录需要匹配的值
         */
        private final String semiology;

        public KeyConversion(){
            this("\\*");
        }
        public KeyConversion(String semiology){
            this.semiology = semiology;
        }

        /**
         * 是否开头
         */
        private boolean isFirst(String key){
            return key.indexOf(semiology) == 0;
        }

        /**
         * 是否结尾
         */
        private boolean isLast(String key){
            return key.lastIndexOf(semiology) == key.length() - 1;
        }

        /**
         * 是否  * 开头和结尾
         */
        private boolean isFirstAndLast(String key){
            if(!isFirst(key)){
                return false;
            }
            if(!isLast(key)){
                return false;
            }
            return true;
        }

        /**
         * 获取key,如 A*
         */
        public Set<String> keyValue(String key){
            if (isFirst(key)){
                key = key.substring(1);
            }
            String[] split = key.split(semiology);
            Set<String> result = new HashSet<>();
            if (split.length == 0){
                return result;
            } else if (split.length == 1){
                result.addAll(oneDate(split[0]));
            } else {
                result = bodyData(split);
            }
            return result;
        }

        private Set<String> oneDate(String key){
            return protoKeys().stream().filter(data -> data.indexOf(key) != -1).collect(Collectors.toSet());
        }

        public String subStr(String str1, String str2){
            int indexOfValue = str1.indexOf(str2);
            if(indexOfValue!=-1){
                return str1.substring(indexOfValue + str2.length());
            }
            return null;
        }

        private Set<String> bodyData(String[] splitStr){
            return protoKeys().stream().filter(data -> {
                for (int i = 0; i < splitStr.length; i++) {
                    data = subStr(data,splitStr[i]);
                    if(data == null){
                        return false;
                    }
                }
                return true;
            }).collect(Collectors.toSet());
        }
    }


    /**
     * 创建CacheObject
     */
    protected CacheObject<V> createNode(V value, long nanosTime){
        CacheObject<V> node = new CacheObject(value, nanosTime < 0 ? 0 : nanosTime, value == null ? null : value.getClass());
        return node;
    }

}
